Actionbook: Build Your First AI Browser Agent

Last updated: February 13 2026

In this tutorial you will build a small Node.js AI agent that uses the Actionbook CLI and Action Manuals to search Google β€” entirely on your local machine. By the end you will understand how action manuals provide pre-computed selectors, how the CLI controls your browser, and how to wire everything together with an LLM.

Actionbook Banner

> What you will build: A command-line agent you run with node agent.mjs "your query". It fetches an action manual for Google, extracts the search input selector, opens your real browser, types the query, and takes a screenshot of the results.

How Actionbook Works

Without Actionbook an AI agent has to download an entire HTML page, parse it, and guess which element to click β€” burning tokens and hallucinating. Actionbook gives the agent Action Manuals instead: pre-computed playbooks with verified selectors for each interactive element on popular websites.

text
Your Agent
  β”‚
  β”œβ”€ actionbook search "google search"        ──►  Find available action manuals
  β”‚                                                 β€’ google.com:/:default
  β”‚                                                 β€’ google.com:/advanced_search:default
  β”‚
  β”œβ”€ actionbook get "google.com:/:default"    ◄──  Full manual with selectors
  β”‚                                                 β€’ textarea_search: textarea[aria-label="Search"]
  β”‚                                                 β€’ button_search: [aria-label="Google Search"]
  β”‚
  β”œβ”€ actionbook browser open "google.com"     ──►  Your real Chrome/Edge/Brave
  β”‚                                                 (connected via CDP β€” no driver install)
  β”‚
  └─ actionbook browser fill / press          ──►  Execute actions using verified selectors

The CLI is written in Rust and connects to the browser you already have installed β€” nothing extra to download. Action manuals are maintained and versioned by Actionbook, so when a site changes, the manual is updated β€” not your agent.

Prerequisites

Before you start, make sure you have:

  • Node.js 18+ β€” check with node --version
  • Chrome, Brave, Edge, or Arc already installed on your machine
  • An OpenAI API key (free tier works) β€” you will store it in .env
  • A terminal (macOS Terminal, Windows PowerShell, or Linux shell)

Project Structure

Here is every file you will create in this tutorial:

text
my-actionbook-agent/
β”œβ”€β”€ agent.mjs          ← the AI agent that orchestrates everything
β”œβ”€β”€ browser.mjs        ← thin wrapper around Actionbook CLI commands
β”œβ”€β”€ .env               ← your API key (never commit this)
└── package.json

Step 1 β€” Install the Actionbook CLI

Open your terminal and run:

bash
npm install -g @actionbookdev/cli

Verify the install worked:

bash
actionbook --version

You should see a version number printed. If you see a "command not found" error, make sure your npm global bin directory is on your PATH (run npm bin -g to find it).

Step 2 β€” Try the CLI Manually

Before writing any code, let’s explore Actionbook interactively so you understand what your agent will do automatically.

Search for action manuals and explore them:
bash
# Search for Google-related action manuals
actionbook search "google search"

# Get the full action manual for Google homepage
actionbook get "google.com:/:default"
Open your browser and interact with it:
bash
# Open Google in your existing Chrome/Brave/Edge
actionbook browser open "https://www.google.com"

# Fill the search box using a selector from the action manual
actionbook browser fill 'textarea[aria-label="Search"]' "Actionbook browser agent"

# Press Enter to search
actionbook browser press "Enter"

# Take a screenshot to verify
actionbook browser screenshot ./result.png

# Always close when you are done
actionbook browser close

> What just happened? The search command found available action manuals for Google. The get command retrieved the full manual with verified selectors. The CLI then connected to your real browser via Chrome DevTools Protocol (CDP) and executed the automation using those selectors. No WebDriver, no Selenium, no separate Chromium download β€” it used the browser you already have.

Step 3 β€” Create the Project

bash
mkdir my-actionbook-agent
cd my-actionbook-agent
npm init -y
npm install openai dotenv
package.json β€” add "type": "module" so you can use ES modules:
json
{
  "name": "my-actionbook-agent",
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "start": "node agent.mjs"
  },
  "dependencies": {
    "openai": "^4.0.0",
    "dotenv": "^16.0.0"
  }
}
.env β€” paste your key here:
bash
OPENAI_API_KEY=sk-your-key-here

Step 4 β€” browser.mjs β€” CLI Wrapper

This file wraps each Actionbook CLI command in a JavaScript function so your agent can call them easily.

javascript
// browser.mjs
// Wraps Actionbook CLI commands so the agent can call them from JS.
import { execSync } from "node:child_process";

// Run a CLI command and return its stdout as a string.
// opts.stdio = "inherit" lets you see live output in the terminal.
function run(cmd, opts = {}) {
  return execSync(cmd, { encoding: "utf8", ...opts });
}

// ── Action Manual Commands ───────────────────────────────────────────────────

/** Search for action manuals. Returns raw text output from the CLI. */
export function searchActions(query) {
  console.log(`[actionbook] Searching: "${query}"`);
  return run(`actionbook search "${query}"`);
}

/** Fetch the full action manual for an area ID (e.g. "google.com:/:default"). */
export function getManual(areaId) {
  console.log(`[actionbook] Getting manual: ${areaId}`);
  return run(`actionbook get "${areaId}"`);
}

// ── Browser Commands ─────────────────────────────────────────────────────────

/** Open a URL in your existing Chrome/Brave/Edge browser. */
export function browserOpen(url) {
  console.log(`[actionbook] Opening: ${url}`);
  run(`actionbook browser open "${url}"`, { stdio: "inherit" });
}

/** Fill an input field with text (official Actionbook command). */
export function browserFill(selector, text) {
  console.log(`[actionbook] Filling "${text}" into ${selector}`);
  // Use single quotes for selector to avoid escaping issues with attribute selectors
  run(`actionbook browser fill '${selector}' '${text}'`);
}

/** Press a key (e.g., "Enter", "Tab", "Escape"). */
export function browserPressKey(key) {
  console.log(`[actionbook] Pressing key: ${key}`);
  run(`actionbook browser press "${key}"`);
}

/** Take a screenshot. Returns path string. */
export function browserScreenshot(path = "./screenshot.png") {
  run(`actionbook browser screenshot "${path}"`);
  return path;
}

/** Close the browser session. ALWAYS call this when done. */
export function browserClose() {
  console.log(`[actionbook] Closing browser.`);
  try {
    run(`actionbook browser close`);
  } catch {
    // Ignore errors on close β€” browser may already be shut down.
  }
}

Step 5 β€” agent.mjs β€” The AI Agent

This is the brain. It searches for an action manual, extracts the verified selector, then uses browser.mjs to execute the task.

javascript
// agent.mjs
import "dotenv/config";
import OpenAI from "openai";
import {
  searchActions,
  getManual,
  browserOpen,
  browserFill,
  browserPressKey,
  browserScreenshot,
  browserClose,
} from "./browser.mjs";

const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

// ── Step 1: Parse action IDs from search results ────────────────────────────

function parseActionIds(searchOutput) {
  const lines = searchOutput.split("\n");
  const actionIds = [];

  for (const line of lines) {
    // Match "- ID: xxx" format
    const idMatch = line.match(/^- ID:\s*(.+)$/);
    if (idMatch) {
      actionIds.push(idMatch[1].trim());
      continue;
    }
    // Match "### xxx" header format
    const headerMatch = line.match(/^###\s+([\w.-]+:[^\s]+)/);
    if (headerMatch) {
      actionIds.push(headerMatch[1].trim());
    }
  }

  return actionIds;
}

// ── Step 2: Main search task using action manuals ───────────────────────────

async function runSearchTask(query) {
  console.log(`\nπŸ€– Agent starting task: search Google for "${query}"\n`);

  try {
    // Search for Google search action manual
    console.log("[agent] Searching for action manual...");
    const searchResults = searchActions("google search");

    // Parse action IDs from results
    const actionIds = parseActionIds(searchResults);
    console.log("[agent] Found action IDs:", actionIds);

    // Find the Google homepage action
    let actionId = actionIds.find((id) => 
      id.startsWith("google.com:/:") || id === "google.com:/:default"
    );
    if (!actionId) {
      actionId = actionIds.find((id) => id.startsWith("google.com:"));
    }
    if (!actionId) throw new Error("No action manual found for Google");

    // Get the full action manual
    console.log(`[agent] Fetching manual for: ${actionId}`);
    const manual = getManual(actionId);

    // Extract the search input selector from the role definition
    // The manual contains: getByRole('combobox', { name: 'Search' })
    let searchInputSelector = '[role="combobox"]';
    const roleMatch = manual.match(/getByRole\('combobox',\s*\{\s*name:\s*'([^']+)'\s*\}\)/);
    if (roleMatch) {
      const comboboxName = roleMatch[1];
      console.log(`[agent] Found combobox name: ${comboboxName}`);
      searchInputSelector = `textarea[aria-label="${comboboxName}"]`;
    }
    console.log(`[agent] Using selector: ${searchInputSelector}`);

    // Execute browser automation
    browserOpen("https://www.google.com");
    await new Promise((resolve) => setTimeout(resolve, 1500));

    // Fill the search input and submit
    browserFill(searchInputSelector, query);
    browserPressKey("Enter");

    // Wait for results and screenshot
    await new Promise((resolve) => setTimeout(resolve, 3000));
    const shot = browserScreenshot("./search-result.png");
    console.log(`\nβœ… Done! Screenshot saved to ${shot}`);
  } finally {
    browserClose();
  }
}

// ── Entry point ──────────────────────────────────────────────────────────────

const query = process.argv[2] ?? "Actionbook browser agent";
runSearchTask(query).catch((err) => {
  console.error("\n❌ Agent error:", err.message);
  browserClose();
  process.exit(1);
});

Step 6 β€” Run the Agent

Make sure Chrome (or Brave/Edge) is installed, then run:

bash
node agent.mjs "open source AI agents"

You will see the agent log each step as it goes:

text
πŸ€– Agent starting task: search Google for "open source AI agents"

[agent] Searching for action manual...
[actionbook] Searching: "google search"
[agent] Found action IDs: [ 'google.com:/:default', ... ]
[agent] Fetching manual for: google.com:/:default
[actionbook] Getting manual: google.com:/:default
[agent] Found combobox name: Search
[agent] Using selector: textarea[aria-label="Search"]
[actionbook] Opening: https://www.google.com
βœ“ Google
  https://www.google.com
[actionbook] Filling "open source AI agents" into textarea[aria-label="Search"]
[actionbook] Pressing key: Enter

βœ… Done! Screenshot saved to ./search-result.png
[actionbook] Closing browser.

Open search-result.png and you will see a real Google results page.

Google Search Results

Step 7 β€” Understand What Each Part Does

  • browser.mjs β€” Translates JS function calls into actionbook CLI commands (search, get, browser fill, etc.)
  • agent.mjs β€” Orchestrates the workflow: search for manual β†’ get manual β†’ extract selector β†’ execute browser actions
  • .env β€” Stores secrets β€” never commit this file
Why use Action Manuals? Action manuals are pre-computed playbooks maintained by Actionbook. They contain verified selectors that are updated when websites change. Instead of your agent guessing selectors or parsing full HTML, it uses a curated manual with high-confidence selectors β€” 10x faster and 100x fewer tokens.
What is CDP? Chrome DevTools Protocol is the same protocol your browser's DevTools uses. Actionbook speaks CDP natively, so it can open tabs, click, type, and screenshot without any driver or browser extension.

Next Steps

Now that your first agent works, here is what to try next:

  • Add more sites β€” run actionbook search "linkedin login" and automate LinkedIn.
  • Loop over queries β€” read a list of search terms from a file and run the agent for each.
  • Chain actions β€” after the search, get another manual for the results page and follow a link.
  • Add the MCP server β€” once comfortable with the CLI, add the MCP server to Cursor or Claude Code so your AI IDE can call Actionbook for you automatically.

Resources